[name].tsx 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. import { Head } from "fresh/runtime";
  2. import { page, type PageProps } from "fresh";
  3. import { find } from "utils/db.ts";
  4. import { define } from "utils/state.ts";
  5. import PostList from "../../islands/PostList.tsx";
  6. import ThemeToggle from "../../islands/ThemeToggle.tsx";
  7. import PageContainer from "../../components/layout/PageContainer.tsx";
  8. interface UserPageProps {
  9. userName: string;
  10. posts: {
  11. id: string;
  12. title: string;
  13. content: string;
  14. shared: boolean;
  15. hasPassword: boolean;
  16. }[];
  17. notFound: boolean;
  18. }
  19. export const handler = define.handlers({
  20. GET(ctx) {
  21. const name = ctx.params.name;
  22. const user = find("User", { name }, ["id"]);
  23. if (user.length === 0) {
  24. return page({ userName: name, posts: [], notFound: true });
  25. }
  26. const userId = user[0]["id"] as number;
  27. const posts = find("Post", { user_id: userId, shared: 1 }, [
  28. "id",
  29. "title",
  30. "content",
  31. "shared",
  32. "share_password",
  33. ]);
  34. if (posts.length === 0) {
  35. return page({ userName: name, posts: [], notFound: true });
  36. }
  37. return page({
  38. userName: name,
  39. posts: posts.map((post) => ({
  40. id: post["id"] as string,
  41. title: post["title"] as string,
  42. content: post["content"] as string,
  43. shared: post["shared"] === 1,
  44. hasPassword: Boolean(post["share_password"]),
  45. })),
  46. notFound: false,
  47. });
  48. },
  49. });
  50. export default define.page((props: PageProps<UserPageProps>) => {
  51. const { userName, posts, notFound } = props.data;
  52. if (notFound) {
  53. return (
  54. <>
  55. <Head>
  56. <title>Not Found</title>
  57. </Head>
  58. <PageContainer centered>
  59. <div className="absolute top-3 right-3">
  60. <ThemeToggle />
  61. </div>
  62. <span className="text-xl text-gray-500 dark:text-gray-400">
  63. Page not found
  64. </span>
  65. </PageContainer>
  66. </>
  67. );
  68. }
  69. return (
  70. <>
  71. <Head>
  72. <title>{userName}'s Posts</title>
  73. </Head>
  74. <PageContainer>
  75. <div className="absolute top-3 right-3">
  76. <ThemeToggle />
  77. </div>
  78. <h1 className="text-2xl font-bold mt-2">{userName}'s Posts</h1>
  79. <PostList posts={posts} readOnly />
  80. </PageContainer>
  81. </>
  82. );
  83. });